home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Celestin Apprentice 5
/
Apprentice-Release5.iso
/
Information
/
CSMP Digest
/
volume 3
/
csmp-digest-v3-134
< prev
next >
Wrap
Text File
|
1996-02-04
|
90KB
|
2,319 lines
C.S.M.P. Digest Fri, 02 Feb 96 Volume 3 : Issue 134
Today's Topics:
Announcing TransSkel++
AppleScript : date to string ?
Does the DriverInstall trap really exist?
Extending Finder Drag and Drop
How to set the job name when printing?
How to think about Undo
Landmass Algorithm?
Print Jobs again - naming & copy control
Problems with UPP's
Q: Do QuickDraw routines execute faster Offscreen?
SetCCursor inside a VBL task?
Using STL with pointers to objects
VBL synching (again)
The Comp.Sys.Mac.Programmer Digest is moderated by Francois Pottier
(pottier@clipper.ens.fr).
The digest is a collection of article threads from the internet
newsgroups comp.sys.mac.programmer.help, csmp.tools, csmp.misc and
csmp.games. It is designed for people who read news semi-regularly and
want an archive of the discussions. If you don't know what a
newsgroup is, you probably don't have access to it. Ask your systems
administrator(s) for details. If you don't have access to news, you
may still be able to post messages to the group by using a mail server
like anon.penet.fi (mail help@anon.penet.fi for more information).
Each issue of the digest contains one or more sets of articles (called
threads), with each set corresponding to a 'discussion' of a particular
subject. The articles are not edited; all articles included in this digest
are in their original posted form (as received by our news server at
nef.ens.fr). Article threads are not added to the digest until the last
article added to the thread is at least two weeks old (this is to ensure that
the thread is dead before adding it to the digest). Article threads that
consist of only one message are generally not included in the digest.
The digest is officially distributed by two means, by email and ftp.
If you want to receive the digest by mail, send email to listserv@ens.fr
with no subject and one of the following commands as body:
help Sends you a summary of commands
subscribe csmp-digest Your Name Adds you to the mailing list
signoff csmp-digest Removes you from the list
Once you have subscribed, you will automatically receive each new
issue as it is created.
The official ftp info is ftp://ftp.dartmouth.edu/pub/csmp-digest.
Questions related to the ftp site should be directed to
scott.silver@dartmouth.edu.
-------------------------------------------------------
>From fadushin@top.cis.syr.edu (Fred Dushin)
Subject: Announcing TransSkel++
Date: 18 Jan 1996 04:51:30 GMT
Organization: Syracuse University, CIS Dept.
Announcing...
TransSkel++
A C++ Class Framework based on TransSkel
What is TransSkel++?
TransSkel++ is a C++ module which runs on top of TransSkel, a freely
distributed Macintosh application skeleton written in C (and
Pascal). TransSkel++ provides an intuitive and easy-to-use
interface to TransSkel for the C++ programmer. In addition,
TransSkel++ provides a simple class framework for developing
Macintosh applications.
What advantages does TransSkel++ have over TransSkel?
TransSkel++ is written in C++. C++ programs using TransSkel
are in the awkward position of having to declare all TransSkel
callback routines as C functions. While this is a relatively
simple hurdle to overcome, it soon becomes tiring. TransSkel++
helps to alleviate some of this tedium.
In addition, TransSkel++ extends the object-oriented paradigm used
in TransSkel to define a simple set of base classes corresponding to
the sorts of object users have come to expect in a Macintosh
program: menus, windows, and dialogs. With TransSkel++, programmers
may create instances of these or subclasses of these classes which
automatically respond to events in a program (updates, mouse clicks,
etc.) by using the event-routing mechanisms in TransSkel.
TransSkel++'s use of class hierarchies means a slight reduction in
code duplication and better opportunity for modular code over that
in TransSkel projects.
What advantages does TransSkel have over TransSkel++?
TransSkel++ is written in C++. Many users of C find C++ to be
a language which spoils the simplicity of the C language.
Classes, polymorphism, call by reference, and inheritance
introduce subtle issues in a language which originally gained
popularity for its elegant syntax and semantics. C++ has
(perhaps rightly) been criticized for contaminating the purity of C.
On the other hand, C++ provides an appropriate platform
for experiment with object oriented programming for the C
programmer; users of C need not learn an entirely new syntax in
order to explore the concepts involved in object-oriented
programming. Macintosh C programmers may therefore find TransSkel++
to provide a suitable introduction to object oriented programming on
the Macintosh.
How can I get TransSkel++?
TransSkel++ is available via the World Wide Web at the URL:
http://web.syr.edu/~fadushin/TransSkel++
The TransSkel++ package includes source code and projects
for Symantec C++ 7.0.4. In addition, the package includes
demonstration programs and full documentation.
TransSkel++ runs on top of TransSkel release 3.23 (without
modification). You must first install TransSkel 3.23 before
using TransSkel++. TransSkel 3.23 is available via the URL:
http://www.primate.wisc.edu/software/mac/TransSkel
Like TransSkel, TransSkel++ is free and may be used without
restriction.
I would be interested in hearing comments, bug reports, or
suggestions for improvement about TransSkel++. I may be
reached via the internet at
fadushin@top.cis.syr.edu.
/*
* Fred Dushin
* School of Computer and Information Science
* 2-120 CST
* Syracuse University
* Syracuse, NY 13244
*
* http://web.syr.edu/~fadushin
*/
---------------------------
>From Philippe Gachon <p_gachon@supaero.fr>
Subject: AppleScript : date to string ?
Date: Mon, 15 Jan 1996 13:30:24 +0100
Organization: supaero
With AppleScript, how can I convert date to string ?
(In fact, I want to rename a file to the current date.)
Thank you in advance.
--
+----------------------------+ ___ _ _ _ _ _ ___ ___ ___
| Philippe.Gachon@supaero.fr | |__] |__| | | | |__] |__] |_
+----------------------------+ | | | | |__ | | | |__
+++++++++++++++++++++++++++
>From technic@seanet.com (Ronald N. Tjoelker)
Date: Wed, 17 Jan 1996 22:12:51 -0800
Organization: Seanet Online Services, Seattle WA
In article <30FA48E0.3B95@supaero.fr>, Philippe Gachon
<p_gachon@supaero.fr> wrote:
> With AppleScript, how can I convert date to string ?
Try:
set myString to (current date) as string
---------------------------
>From nagle@netcom.com (John Nagle)
Subject: Does the DriverInstall trap really exist?
Date: Sun, 14 Jan 1996 03:43:45 GMT
Organization: NETCOM On-line Communication Services (408 261-4700 guest)
DriverInstall is documented in IM-Devices, on page 1-83,
and there's a nice technote, DV-23, about it. But it's not
in <Devices.h>. Instead, there's a comment:
Note: DrvrInstall() is no longer supported, becuase it never really
worked anyways.
There will soon be a DriverInstall() which does the right thing.
There's no sign at all of DriverInstallReserveMem in the headers,
although it, too, is documented in IM-Devices.
So how do you install a unit table entry for something that supports
several driver names from a single driver? Is this just an error
in the headers, or is there really no DriverInstall?
John Nagle
+++++++++++++++++++++++++++
>From jumplong@aol.com (Jump Long)
Date: 15 Jan 1996 10:55:44 -0500
Organization: America Online, Inc. (1-800-827-6364)
John Nagle wrote:
>DriverInstall is documented in IM-Devices, on page 1-83, and
>there's a nice technote, DV-23, about it. But it's not in
><Devices.h>. Instead, there's a comment:
>
> Note: DrvrInstall() is no longer supported, becuase it never
> really worked anyways.
> There will soon be a DriverInstall() which does the right
> thing.
>
>There's no sign at all of DriverInstallReserveMem in the
>headers, although it, too, is documented in IM-Devices.
>
>So how do you install a unit table entry for something that
>supports several driver names from a single driver? Is this
>just an error in the headers, or is there really no
>DriverInstall?
Yes, DrvrInstall in ROM has a bug and shouldn't be used.
Check out Apple's RAMDisk sample. I wrote the DriverInstall replacement
routine for RAMDisk that doesn't have the bug. The RAMDisk sample also has
many other routines (like code to: grow the UnitTable safely, find a
unused entry driver reference number, and remove a driver) you may find
useful if you're writing a driver or a disk driver.
RAMDisk can be found on the Tool Chest edition of Apple's Developer CD and
at:
ftp://sam.austin.apple.com/Apple.Support.Area/Developer_Services/Sample_Co
de//RAMDisk_1.2/RAMDisk_1.2.sit.hqx
- Jim Luther
---------------------------
>From peter@adi.co.nz (Peter Bromley)
Subject: Extending Finder Drag and Drop
Date: Tue, 16 Jan 1996 15:53:06 +1300
Organization: ADInstruments
Does anyone know if the Finder can be made to allow drag files onto
something other than folders or applications? It has been done by Apple -
Powertalk mailbox, etc.
The reason I am asking is that an Archiving program we are working on
really needs to allow Finder drag and drop onto its archive storage
documents.
TIA,
(Excuse me if this is repeated)
--
Peter Bromley (peter@adi.co.nz)
ADInstruments, Dunedin, New Zealand
+++++++++++++++++++++++++++
>From chris-b@cs.auckland.ac.nz (Chris Burns)
Date: Wed, 17 Jan 1996 11:30:29 +1300
Organization: HyperMedia Unit, Comp Sci, Auckland University
In article <peter-1601961553060001@adi008.adi.co.nz>, peter@adi.co.nz
(Peter Bromley) wrote:
>Does anyone know if the Finder can be made to allow drag files onto
>something other than folders or applications? It has been done by Apple -
>Powertalk mailbox, etc.
>
>The reason I am asking is that an Archiving program we are working on
>really needs to allow Finder drag and drop onto its archive storage
>documents.
Just make your "archive storage documents" very small applications that
call your "Archiving program" with the right AppleEvents...
Chris B
- ---------------------------------------------------------------------
NewZealand:AucklandUniversity:ComputerScience:HyperMediaUnit:ChrisBurns
Internet: chris-b@cs.auckland.ac.nz
Phone: +64 9 373-7599 x5602
Fax: +64 9 373-7453 Async, Therefore I Am.
- ---------------------------------------------------------------------
---------------------------
>From sdr@sdr.com.au (Roger Lainson)
Subject: How to set the job name when printing?
Date: Wed, 10 Jan 1996 00:05:26 GMT
Organization: SDR
Does anyone know how to control the name of the print job created by
PrOpen(), as seen in the Print Monitor?
I'm doing a lot of printing from my own XCMD in HyperCard, and at present
every job simply takes the name of the stack (or "Message" if the XCMD is
invoked from HC's message box). I'd like to be able to generate my own job
names. Any suggestions, please?
Roger Lainson.
- -----------------------SDR Clinical Technology------------------------
213 Eastern Valley Way, Middle Cove, NSW 2068, Australia
Voice: +61-2-9958-2688 Fax: +61-2-9958-2655 email: sdr@sdr.com.au
World Wide Web: http://www.sdr.com.au/sdr/index.html
- ----------------------------------------------------------------------
+++++++++++++++++++++++++++
>From gregb@genmagic.com (Greg Branche)
Date: Tue, 09 Jan 1996 17:36:20 -0800
Organization: General Magic
In article <sdr-1001961105260001@gateway.sdr.com.au>, sdr@sdr.com.au
(Roger Lainson) wrote:
>Does anyone know how to control the name of the print job created by
>PrOpen(), as seen in the Print Monitor?
>
>I'm doing a lot of printing from my own XCMD in HyperCard, and at present
>every job simply takes the name of the stack (or "Message" if the XCMD is
>invoked from HC's message box). I'd like to be able to generate my own job
>names. Any suggestions, please?
>
The MPW Print tool has the same problem with LaserWriter 8 drivers. The
problem does not exist with earlier drivers.
I think the problem is that the driver assumes that the object being
printed is the frontmost window, and so it looks through the window list
to determine the title of the window to use as the name of the print job.
I wrote this up in Apple's bug tracking system a couple of years ago, long
before I lost access to the database.
Greg Branche
Magic Cap Entomologist
General Magic, Inc.
+++++++++++++++++++++++++++
>From jjohnson@crl.com (Jeffrey Johnson)
Date: 10 Jan 1996 01:51:01 GMT
Organization: CRL Dialup Internet Access (415) 705-6060 [Login: guest]
Roger Lainson (sdr@sdr.com.au) wrote:
: Does anyone know how to control the name of the print job created by
: PrOpen(), as seen in the Print Monitor?
:
: I'm doing a lot of printing from my own XCMD in HyperCard, and at present
: every job simply takes the name of the stack (or "Message" if the XCMD is
: invoked from HC's message box). I'd like to be able to generate my own job
: names. Any suggestions, please?
:
I believe that PrintMonitor takes the title of the frontmost window as its
job title (it's been a while). Try opening a dummy documentProc window at
coordinates outside the screen before you start the job and then kill it
when the job is done...
Thanks
Jeff
__
Jeffrey Johnson jjohnson@crl.com
If you believe what you read, the sky is thick with aliens who are designing
pyramids, disemboweling livestock, impregnating rural people and generally
having a good time at our expense. -Scott Adams
+++++++++++++++++++++++++++
>From Carl R. Osterwald <carl_osterwald@nrel.gov>
Date: 10 Jan 1996 16:48:03 GMT
Organization: National Renewable Energy Laboratory
In article <4cv625$3mu@nntp.crl.com> Jeffrey Johnson, jjohnson@crl.com
writes:
>Roger Lainson (sdr@sdr.com.au) wrote:
>: Does anyone know how to control the name of the print job created by
>: PrOpen(), as seen in the Print Monitor?
>: I'm doing a lot of printing from my own XCMD in HyperCard, and at present
>: every job simply takes the name of the stack (or "Message" if the XCMD is
>: invoked from HC's message box). I'd like to be able to generate my own job
>: names. Any suggestions, please?
>I believe that PrintMonitor takes the title of the frontmost window as its
>job title (it's been a while). Try opening a dummy documentProc window at
>coordinates outside the screen before you start the job and then kill it
>when the job is done...
This has to be done carefully to avoid any unsightly highlighting/
dehighlighting of other windows. Also, if you have a floating window
that is always on top, you can just change its title to the title of the
window being printed (assuming that its title is never visible, i.e. it
is a windoid).
+++++++++++++++++++++++++++
>From skevill@tartarus.uwa.edu.au (Scott Kevill)
Date: Thu, 11 Jan 1996 01:46:54 +0800
Organization: The University of Western Australia
In article <sdr-1001961105260001@gateway.sdr.com.au>, sdr@sdr.com.au
(Roger Lainson) wrote:
: Does anyone know how to control the name of the print job created by
: PrOpen(), as seen in the Print Monitor?
:
: I'm doing a lot of printing from my own XCMD in HyperCard, and at present
: every job simply takes the name of the stack (or "Message" if the XCMD is
: invoked from HC's message box). I'd like to be able to generate my own job
: names. Any suggestions, please?
:
: Roger Lainson.
:
: -------------------------SDR Clinical Technology------------------------
: 213 Eastern Valley Way, Middle Cove, NSW 2068, Australia
: Voice: +61-2-9958-2688 Fax: +61-2-9958-2655 email: sdr@sdr.com.au
: World Wide Web: http://www.sdr.com.au/sdr/index.html
: ------------------------------------------------------------------------
Hmm.. I seem to remember it takes the name of the frontmost window, so try
creating a window offscreen with the name you desire and remove it after
printing.
Hope this helps,
Scott Kevill.
skevill@tartarus.uwa.edu.au
+++++++++++++++++++++++++++
>From reed@medicine.wustl.edu (Thomas Reed)
Date: Thu, 11 Jan 1996 12:30:52 -0600
Organization: Washington University
In article <sdr-1001961105260001@gateway.sdr.com.au>, sdr@sdr.com.au
(Roger Lainson) wrote:
>Does anyone know how to control the name of the print job created by
>PrOpen(), as seen in the Print Monitor?
The job name is obtained from the frontmost window. You should be able to
just create something like a print status window before initiating the
print job, and name this new window whatever you want the job named. Of
course, someone else did bring up a good point about floaters. Dunno how
they'll be handled...
-Thomas
=====================================================
Thomas Reed Washington University
reed@visar.wustl.edu Medical School
reed@medicine.wustl.edu Saint Louis, MO
http://medinfo.wustl.edu/~reed
- ---------------------------------------------------
Clothes make the man. Naked people have little or no
influence on society. -- Mark Twain
=====================================================
Opinions posted are not the opinions of Wash. U.
+++++++++++++++++++++++++++
>From mouser@zercom.net (Martin-Gilles Lavoie)
Date: Thu, 11 Jan 1996 11:04:27 -0500
Organization: Groupimage, inc.
In article <sdr-1001961105260001@gateway.sdr.com.au>, sdr@sdr.com.au
(Roger Lainson) wrote:
> Does anyone know how to control the name of the print job created by
> PrOpen(), as seen in the Print Monitor?
>
> I'm doing a lot of printing from my own XCMD in HyperCard, and at present
> every job simply takes the name of the stack (or "Message" if the XCMD is
> invoked from HC's message box). I'd like to be able to generate my own job
> names. Any suggestions, please?
>
> Roger Lainson.
>
The printing Manager's default behaviour is to use the front window's
title as the job name.
One way to change this behaviour is to create a "status dialog" while you
print (wich say, for example, "printing page X of Y"). If this window is
grought up before PrOpen(), the Printing Manager will use that window's
title as job name. So, you can override the job name by changing your
dialog title before printing. Many apps do this.
MGL
+++++++++++++++++++++++++++
>From McMath_C@mediasoft.net (Chuck E's In Love... McMath)
Date: Mon, 15 Jan 1996 09:14:01 -0500
Organization: Reed Technology & Information Services, Inc.
In article <sdr-1001961105260001@gateway.sdr.com.au>, sdr@sdr.com.au
(Roger Lainson) wrote:
> Does anyone know how to control the name of the print job created by
> PrOpen(), as seen in the Print Monitor?
>
> I'm doing a lot of printing from my own XCMD in HyperCard, and at present
> every job simply takes the name of the stack (or "Message" if the XCMD is
> invoked from HC's message box). I'd like to be able to generate my own job
> names. Any suggestions, please?
>
I thought I read somewhere that the print manager picks up the name of the
front document as the job. That's why if you put up one of those 'press
command-period to cancel dialogs you get something like 'Untitled'.
The suggestion for having your own job names was to create a small window
off-screen; give this window the name that you want to appear in the print
manager window. I believe I've done this and it works.
Hope this helps,
chuck
|-- Chuck McMath -- McMath_C@mediasoft.net -or-- chuck@ocs.com -----|
|-- Reed Technology & Information Services, Inc. -------------------|
|-- 20251 Century Blvd. -- Germantown, MD 20874 -------------------|
|-------------- "Hey Batter, Hey Batter, swing!" - Anon.------------|
|--------------- My Karma Ran Over My Dogma ------------------------|
---------------------------
>From kurisuto@babel.ling.upenn.edu (Sean Crist)
Subject: How to think about Undo
Date: 10 Jan 1996 03:52:56 GMT
Organization: University of Pennsylvania
How do you implement the Undo command? This is such a broad question, and
once whose specific answer will vary so much depending on the particular
application, that I'm not even sure how meaningful it is to ask it. But
I'm interested in finding some coherent way to think about the problem.
By way of example, suppose I'm writing a simple object-oriented graphics
application (like MacDraw). Suppose there are four graphic objects, each
with a different fill pattern; the user selects all four and changes their
pattern to something else. To Undo this, I somehow have to remember the
four original patterns of the selected objects. I can think of at least
two paradigms for thinking about Undo here:
Paradigm 1: Whatever the data structure is in which I store these objects
(an array, say), I keep two whole structures: the version before the
change, and the version after the change. I implement Undo/Redo by
swapping these back and forth. This roughly doubles the amount of memory
needed for the data, but is relatively simple to code.
Paradigm 2: I keep only one copy of the data structure, but I make a list
of operations which have to be performed to Do/Redo and Undo the action, in
some unseen, application-internal format. For example, when the user
changes the pattern of the four selected items, this translates into a
Do/Redo list which in English means something like the following:
Change the pattern of object 1 to pattern 5
Change the pattern of object 2 to pattern 5
Change the pattern of object 3 to pattern 5
Change the pattern of object 4 to pattern 5
At the time the user performs the command, I also compose a list of Undo
operations, i.e. operations which have to be done to put things back in
their previous state:
Change the pattern of object 1 to pattern 2
Change the pattern of object 2 to pattern 17
Change the pattern of object 3 to pattern 3
Change the pattern of object 4 to pattern 10
To Undo/Redo, I alterately execute these two lists of operations. This
paradigm requires less memory for data, but it requires an extra level of
representation between the user interface and the data, which could add
greatly to the coding complexity.
Thoughts? I have many more questions and ideas, but do either of these
approaches seem to be on the right track? And is it normal to feel that
this one dinky command alone is half the work of coding an application?
\/ __ __ _\_ --Sean Crist (kurisuto@unagi.cis.upenn.edu)
--- | | \ / For a free copy of the Bill of Rights, finger
_| ,| ,| ----- this account. It's also available through
_| ,| ,| [_] my homepage:
| | | [_] http://babel.ling.upenn.edu/~kurisuto/homepage.html
+++++++++++++++++++++++++++
>From kenlong@netcom.com (Ken Long)
Date: Wed, 10 Jan 1996 08:11:43 GMT
Organization: NETCOM On-line Communication Services (408 261-4700 guest)
Color It! has 15 levels of undo. Gunshy has as many levels of undo as it
has "do".
Color It! still has redo for the last one, but you can, "Undo, Redo,
Undo" and still continue to undo as many levels back as it goes. How
does it do it? Temporary files.
Gunshy probably uses an array, but it can only go so far because it only
has so many icons.
So, in Color It!, you're probably looking at a queue - like the queue in
Moire or ZoomIdle or some such (Electric Fire AD mod.). if (numTemp > 15)
remove (firstFile);..., or some such. If you don't have enough disk
space, you get an alert saying the "undo buffer" could not be created.
But the "buffer" would consist of whatever RAM based tracking of the temp
files, plus a multiplier of space comparable to the file size of the file
being worked on, for the temp files.
I'd bet the temp files were not as big as the original, but contained a
portion which dealt with the "done" part. No matter how many actions
were done - even if over 15 - there would still need to be retained the
original for "revert to saved" to happen.
Those are mt "ideas" on it.
-Ken-
+++++++++++++++++++++++++++
>From pottier@drakkar.ens.fr (Francois Pottier)
Date: 10 Jan 1996 13:31:19 GMT
Organization: Ecole Normale Superieure, Paris
In article <4cvd6o$24d@netnews.upenn.edu>,
Sean Crist <kurisuto@babel.ling.upenn.edu> wrote:
>Paradigm 2: I keep only one copy of the data structure, but I make a list
>of operations which have to be performed to Do/Redo and Undo the action, in
This has the advantage that it takes relatively little memory, so you
can actually have many levels of Undo using this method, while it
would probably be impractical using the other method.
>some unseen, application-internal format.
If your application is scriptable, the natural format to use for these
commands would probably be Apple events. I think you should have a look
at the code in PowerPlant (and possibly other frameworks) which has code
to handle Undo/Redo.
> And is it normal to feel that this one dinky command alone is half
> the work of coding an application?
Sure. This is why most applications leave it out - only serious, real
ones implement it.
--
Francois
pottier@dmi.ens.fr
http://www.eleves.ens.fr:8080/home/pottier/
+++++++++++++++++++++++++++
>From DaveZ@mailbag.com (David B. Zwiefelhofer)
Date: Wed, 10 Jan 1996 10:10:11 -0500
Organization: Utility Reduction Specialists, Inc.
In article <4d0f37$ifs@nef.ens.fr>, pottier@drakkar.ens.fr (Francois
Pottier) wrote:
[snip]
>
> Sure. This is why most applications leave it out - only serious, real
> ones implement it.
>
Yeah, I guess that's kind of true. I recently added undo for text input in
the dialogs of a utility I'm working on. I wanted to get a feel for
precisely how undo should behave. Of course, I went to an Apple app to
check it out, SimpleText, and lo and behold, no undo!
-Dave
--
David B. Zwiefelhofer
Utility Reduction Specialists, Inc.
1605 Monroe Street, Suite 110
Madison, WI 53211-2052
(608) 258-8965
(608) 258-9686 FAX
+++++++++++++++++++++++++++
>From rick@kagi.com (Rick Holzgrafe)
Date: Thu, 11 Jan 1996 14:38:09 -0800
Organization: Semicolon Software
In article <4cvd6o$24d@netnews.upenn.edu>, kurisuto@babel.ling.upenn.edu
(Sean Crist) wrote:
> Paradigm 1: Whatever the data structure is in which I store these objects
> (an array, say), I keep two whole structures: the version before the
> change, and the version after the change. I implement Undo/Redo by
> swapping these back and forth. This roughly doubles the amount of memory
> needed for the data, but is relatively simple to code.
>
> Paradigm 2: I keep only one copy of the data structure, but I make a list
> of operations which have to be performed to Do/Redo and Undo the action, in
> some unseen, application-internal format. [...] This
> paradigm requires less memory for data, but it requires an extra level of
> representation between the user interface and the data, which could add
> greatly to the coding complexity.
In an object-oriented approach, for each undoable operation you would
define a "command" class. The command class knows both how to execute the
operation and how to undo it. It is a subclass of a generic command class:
from the generic class it inherits Do and Undo methods which it overrides
to do its particular work, and it adds its own specific and appropriate
kinds of data storage.
If you are not using an object-oriented language, you can accomplish the
same effect with data structures which include function pointers to their
Do and Undo routines.
There is value to this approach that goes beyond simple Undo. All of your
app's operations can be accomplished by first creating an appropriate
command object (or struct, record, whatever) and then calling its Do
routine. This is a nice way to separate the user interface from the
working guts of the program: all a control does is create a command and
then tell it to Do. It becomes simple to add alternate controls, or to
completely change the entire user interface. Your application becomes
easily scriptable (well, more easily) since the scripting interface
becomes just another set of "controls" that create and then execute
command objects. It allows easy, effective journaling -- to keep a record
of the user's operations, you just keep an ordered list of all the command
objects that have been created and executed. Extended or unlimited
undo/redo becomes simple: just keep that same list, with a pointer to
"where you are" in the list. For repeated undos, just back up the pointer
and call the Undo routine. To redo, move the pointer forward and call the
Redo routine. The only limit is available memory, and with careful design
most command objects may be small enough to be negligible in size.
There's more to it than that, of course. It's important to have no
non-undoable operations, difficult though that may be; otherwise you have
to throw away the entire undo history whenever a non-undoable action is
performed. If the user undoes a bunch of commands and then does something
new, remember to throw away everything in the list from the most recently
undone command forward. (Or you could make a branching tree structure, but
I have no idea how you'd make that comprehensible to the user.) Sometimes
what feels like a single operation to the user is really a sequence of
internal command; then you need a way to group command objects so they can
be undone and redone as a batch, to preserve the user's feeling that the
operation was atomic.
>And is it normal to feel that
> this one dinky command alone is half the work of coding an application?
Well, yes. It's not a "dinky command"; it is (or should be) rooted deeply
in the architecture of your application. Coding up all those subclasses of
the command class is indeed tedious, but it really pays off.
-- Rick Holzgrafe
Semicolon Software
rick@kagi.com
http://www.opendoor.com/Rick/Semicolon.html
+++++++++++++++++++++++++++
>From snozer@cats.ucsc.edu (Daniel Craig Jalkut)
Date: 19 Jan 1996 20:57:56 GMT
Organization: University of California, Santa Cruz
In <4dlv8k$ff1@newsbf02.news.aol.com> mrmikeyh@aol.com (MrMikeyH) writes:
>It's these really difficult to implement features that make Macs so
>wonderful to use. Things like point and click, pasting from one
>application to another. These all require a tremendous amount of work.
>But I could not imagine working without Undo. It would be a blaspheme to
>ask my end users to work without it.
>Mike
Do they require a trememdous amount of work?
"point and click" -- is handled very simply by the Macintosh event handler.
The application has the easiest time, merely asking "what happened" and
basically having the toolbox nudge Application towards the correct response
code.
"pasting from one application to another" -- is incredibly easy to implement
thanks to the Scrap manager in, you guessed it, the toolbox.
"undo" -- is extremely simple with one-step undo, where you are only ever
allowed to revert to the state of the program before the last action. If
you add a stack structure, you can easily provide "infinite" undo, which
is a lot more exciting than undo and also checks in at relatively "simple"
as far as coding.
--
_______
Daniel Craig Jalkut "All I know is that I don't know nothing,
snozer@cats.ucsc.edu and that's FINE" -- Operation Ivy
Macintosh enthusiast, BeBox independent developer in waiting.
---------------------------
>From pmiller@mmm.com (Phil Miller)
Subject: Landmass Algorithm?
Date: Wed, 10 Jan 1996 12:20:45 -0600
Organization: 3M
I'm writing a game which will need to create a random
world map -- areas of landmass surrounded by water. I've
tried a couple of algorithms to generate the land with
limited success.
I'm representing the world map as a two dimensional array
which I initialize to all zeros.
The best algorithm to date starts with several "seeds"
distributed more or less randomly in the map array. Then
I recursively examine the array and if I see a non-zero value,
I use some logic to decide whether or not to make the
neighbors around that element non-zero as well.
This algorithm tends to make land masses that look more
like spots of mold in a petri dish rather than things that
look like continents. I can change the shape of the
"mold colonies" by altering the logic in the algorithm,
but I still don't get things that look like continents.
I've toyed with some other ideas to try to mimic how
real continents are formed such as:
1) Creating some imaginary "fault lines" throughout
the world and seeding continents on those lines to mimic
real continent placement
or
2) Creating random landmasses and moving them around
randomly as if they're riding on tectonic plates. Places
of collision become mountain ranges, etc.
I haven't written any code to see how these ideas will
work out yet. Does anybody have any bright ideas that I
could try?
Thanks
Phil Miller
pmiller@mmm.com
Opinions expressed herein are my own and may not represent those of 3M.
+++++++++++++++++++++++++++
>From dangit@netcom.com (Lam Dang)
Date: Thu, 11 Jan 1996 00:31:33 GMT
Organization: NETCOM On-line Communication Services (408 261-4700 guest)
Phil Miller (pmiller@mmm.com) wrote:
: I'm writing a game which will need to create a random
: world map -- areas of landmass surrounded by water. I've
Ok, the following is a typical fractal land generator, but I don't
quite remember any references to text, so...
This is going to be a recursive type deal. Ok, so you have an 2D
array of dimensions WIDTH and HEIGHT, with values from 0 to MAXVAL.
You start off by putting random values in the four corners. In the
middle of the rectangle, you put the average of the corner values.
Do the exact same thing for the four new rectangles you create.
(i.e., topleft, topright, bottomleft, bottomright). You stop
recursing when the middle pixel you are filling in is the same as the
'corner' pixel.
This creates a nice looking texture. You can arbitrarily set the
water 'depth', to see how it looks. Playing with the inital four
corner values dramatically alters the result. Also, instead of a
straight average, you can do an average (+/-) value, or whatnot.
However, i think that this tends not to make planet-like maps; it looks more
like river beds, etc. Problem is that continents are shaped thru magma
flows, etc... You could start by creating random polygons, that follow a
certain 'continent' rule, then do a similar algorithm, but with polygons,
instead of rects... could get complicated tho!
-jD
--
Lam Dang
dangit@netcom.com
+++++++++++++++++++++++++++
>From Kyle Dean <kaschei@cs.su.oz.au>
Date: Thu, 11 Jan 1996 16:14:15 +1100
Organization: Basser Dept of Computer Science, University of Sydney, Australia
One method I've seen and used to create good looking terrain is through
fractals and recursive algorithms.
The basic idea is to roughly generate some terrain, and then fill in the
bits.
So you start with your two dimensional array, initialised to zeros,
which here will represent the altitude of the land of your world.
Then you call a recursive procedure to fill it in, which takes the map,
and the co-ordinates of the rectangle to be filled in.
If the rectangle is "too small" (ie zero or one units wide or tall),
then no work has to be done, and you're finished.
Otherwise, find the co-ordinates of the mid-points of each side. Set the
altitude of the mid-point of each side to be the average of the
altitudes of the end-points of that side PLUS (this is the trick!) a
random numer TIMES the length of that side. Do a similar thing with the
centre of the rectangle (ie average of corners + random proportion of
diagonal). Then call your recursive procedure with each of the four
smaller rectangles.
When the first call to the recursive procedure returns, the world will
be generated, complete down to the fiddly bits. It looks like a mountain
range - just pick a sealevel and get islands/continents. If your random
numbers range evenly from +/- N, then you can use zero as sealevel.
Negative altitudes are water, postive land. (zero is prime beachfront!)
typedef int **WorldMap;
void GenerateWorld(WorldMap map, Rect r)
{
int width = (r.right - r.left);
int height = (r.bottom - r.top);
int midH = (r.left + r.right) / 2; // middle x co-ord
int midV = (r.top + r.bottom) / 2; // middle y co-ord
Rect closer; // next recursion
if ( (width < 2) || (height < 2)) // too small
return;
map[midH][r.top] =
( map[r.right][r.top] + map[r.left][r.top]) / 2
+ Random() * width;
// ... etc. for other three mid-points, and the centre
closer.left = r.left;
closer.top = r.top;
closer.right = mid.H;
closer.bottom = midV;
GenerateWorld(map, closer); // recurse: generate top left quad
// ... etc. for other three quadrants
}
Kyle.
Izvinite, ya speshu na avtobus.
+++++++++++++++++++++++++++
>From songer@lexmark.com
Date: Thu, 11 Jan 1996 18:21:15 GMT
Organization: Lexmark International, Lexington, KY
In article <pmiller-1001961220450001@pm37697.mmm.com> pmiller@mmm.com (Phil Miller) writes:
[...]
I'm writing a game which will need to create a random
world map -- areas of landmass surrounded by water. I've
tried a couple of algorithms to generate the land with
limited success.
[...]
Hi!
There was a big discussion of this problem on
rec.games.programmer some time ago. (May be years ago -- I cannot
recall.) It may be worthwhile to go back and check USENET archives to
take a look for it.
Anyway,
-Chris
+++++++++++++++++++++++++++
>From shebs@cygnus.com (Stan Shebs)
Date: 11 Jan 1996 11:53:27 -0800
Organization: Cygnus Support
In article <30F49CA7.2EC8@cs.su.oz.au> Kyle Dean <kaschei@cs.su.oz.au> writes:
[...]
Otherwise, find the co-ordinates of the mid-points of each side. Set the
altitude of the mid-point of each side to be the average of the
altitudes of the end-points of that side PLUS (this is the trick!) a
random numer TIMES the length of that side. Do a similar thing with the
centre of the rectangle (ie average of corners + random proportion of
diagonal). Then call your recursive procedure with each of the four
smaller rectangles.
This algorithm is known to have a serious intrinsic flaw; the
resulting map will very often have horizontal and vertical lines at
the subdivision points. This can be deadly for an exploration game,
since the savvy player will immediately cruise to the midpoints and
then know whether the terrain will be high or low around them, without
actually having to explore. Even for a non-exploration games, the
shapes will have lots of vertical and horizontal mountain ranges, but
very rarely a diagonal one (you can see this in many commercial games
once you know what to look for).
Tricks such as picking random locations along each side instead of the
midpoint don't help much, since the problem is fundamental to the
recursive algorithm. Several years ago, I spent a couple months
trying to fix this algorithm, with no success, and finally switched to
a true fractal algorithm, which just means randomly placing lots of
randomly-sized blobs, some of which raise the elevation, and some of
which lower it. Results were much less predictable and much more
"natural-looking". To see a code example (which has many elaborations
on the basic algorithm, such as user control over the percentages of
sea/swamp/desert/forest etc), look at the file kernel/mkterr.c in the
sources to my game Xconq. See http://www.cygnus.com/~shebs/xconq.html,
or ftp from ftp.cygnus.com, pub/xconq.
Stan Shebs
shebs@cygnus.com
+++++++++++++++++++++++++++
>From zzkbergm@dingo.uq.edu.au (Christoph Bergmann)
Date: Fri, 12 Jan 1996 14:39:06 +1000
Organization: University of Queensland
In article <pmiller-1001961220450001@pm37697.mmm.com>, pmiller@mmm.com
(Phil Miller) wrote:
> The best algorithm to date starts with several "seeds"
> distributed more or less randomly in the map array. Then
> I recursively examine the array and if I see a non-zero value,
> I use some logic to decide whether or not to make the
> neighbors around that element non-zero as well.
>
> This algorithm tends to make land masses that look more
> like spots of mold in a petri dish rather than things that
> look like continents. I can change the shape of the
> "mold colonies" by altering the logic in the algorithm,
> but I still don't get things that look like continents.
> 1) Creating some imaginary "fault lines" throughout
> the world and seeding continents on those lines to mimic
> real continent placement
> or
> 2) Creating random landmasses and moving them around
> randomly as if they're riding on tectonic plates. Places
> of collision become mountain ranges, etc.
>
> I haven't written any code to see how these ideas will
> work out yet. Does anybody have any bright ideas that I
> could try?
hmm. 1 sounds quite reasonable.. pick a point, make a 'squiggly line' from
the point, and seed everything from this..
2 sounds like a waste of time, sure it is realistic, but it would be a
simulation and i dont think the problem calls for this. imo, it is like
simulating molecular movement to do characters in a sprite game.. (well,
not that bad but u get the idea... )
i'd go with something like 1.
maybe make a number of peaks to make mountains, then get it to decide
which ones are closest, ie. pick a random number of continents and bunch
them into this number of continents giving the least overall area/distance
between points or something along these lines.. not to hard to code, maybe
worth trying..
ChrisB
+++++++++++++++++++++++++++
>From rickgenter@aol.com (RickGenter)
Date: 12 Jan 1996 05:18:00 -0500
Organization: America Online, Inc. (1-800-827-6364)
>>>
Does anybody have any bright ideas that I
could try?
<<<
Have each cell in your grid represent an elevation. Populate the entire
grid, randomly raising/lowering the elevation in each cell. (You may want
to do this less randomly to implement mountain ranges, valleys, etc.)
After you're done, pick a level to be sea level, and zero out everything
below that line.
Hope this helps.
Rick Genter
Papyrus Design Group, Inc.
+++++++++++++++++++++++++++
>From thor@telerama.lm.com (Tom Moertel)
Date: 14 Jan 1996 01:59:14 -0500
Organization: Management Science Associates
Stan Shebs (shebs@cygnus.com) wrote:
: In article <30F49CA7.2EC8@cs.su.oz.au> Kyle Dean
: <kaschei@cs.su.oz.au> writes:
: [...]
> > Otherwise, find the co-ordinates of the mid-points of each side.
> > Set the altitude of the mid-point of each side to be the average
> > of the altitudes of the end-points of that side PLUS (this is the
> > trick!) a random numer TIMES the length of that side. Do a
> > similar thing with the centre of the rectangle (ie average of
> > corners + random proportion of diagonal). Then call your
> > recursive procedure with each of the four smaller rectangles.
> This algorithm is known to have a serious intrinsic flaw; the
> resulting map will very often have horizontal and vertical lines
> at the subdivision points. [...]
> Tricks such as picking random locations along each side instead
> of the midpoint don't help much, since the problem is fundamental
> to the recursive algorithm. Several years ago, I spent a couple
> months trying to fix this algorithm, with no success, and finally
> switched to a true fractal algorithm, which just means randomly
> placing lots of randomly-sized blobs, some of which raise the
> elevation, and some of which lower it. Results were much less
> predictable and much more "natural-looking". To see a code
> example (which has many elaborations on the basic algorithm, such
> as user control over the percentages of sea/swamp/desert/forest
> etc), look at the file kernel/mkterr.c in the sources to my game
> Xconq. See http://www.cygnus.com/~shebs/xconq.html, or ftp from
> ftp.cygnus.com, pub/xconq.
You can avoid the horizontal and vertical artifacts by randomly
adjusting *all* the heights, not just the newly-added midpoints.
The recursive method works fine with this simple adjustment. For
some examples of land generated this way, see:
http://www.telerama.com/~thor/fBm/
--
Tom Moertel Interests: Software Engineering,
Symbolic Mathematics,
MSA, Commercial Software Group Algorithms,
thor@telerama.lm.com Itchy-Scratchy Theory.
+++++++++++++++++++++++++++
>From dwgray@aol.com (DWGray)
Date: 15 Jan 1996 09:46:22 -0500
Organization: America Online, Inc. (1-800-827-6364)
I, too, am writing a landmass generator, and have passed through the
'petri-dish' (a very accurate description) stage you mentioned. What I
ended up doing was to separate the "growth" and "erosion" stages so that I
had a long period of landmass expansion, and then about 1/3 to 1/2 as long
period of landmass contraction. The percentages I used to determine if a
particular pixel increased in height was different than the ones I used
for decrease during erosion, so that the mountains created during growth
weren't levelled. You might try this approach.
For seeding, I began with single pixels, then moved on to rectangles, then
decided that seeding mountains on those rectangles generated better
mountains ranges and gave me better chances for areas of hilly country.
The problem I then ran into was that no lakes were created. So, I began
seeding pixels of water _during_ the erosion process. My erosion is
pretty destructive, so I only needed single pixels to create lakes.
The biggest problem I ran into with the algorithm you are currently using
is that of landmasses connected by thin bridges. It makes very
unusual-looking continents if the initial placement of rectangles (or
circles or whatever) aren't close enough together.
Hope this helps,
- Don Gray
p.s. I am currently researching a completely different algorithm that will
give me a lot more control over placement of rivers and towns (always the
most difficult things to make look right) and other geographical features.
It's still in development, so I can't yet say whether it's worthwhile to
use.
---------------------------
>From sdr@sdr.com.au (Roger Lainson)
Subject: Print Jobs again - naming & copy control
Date: Sun, 14 Jan 1996 23:47:08 GMT
Organization: SDR
Thanks to everybody who helped with my query about how to name a printer
job. The concensus of the comments (plus a few experiments) is that the
job name takes the name of the frontmost window, which must be visible but
which can be offscreen. Floaters are ignored (as in FrontWindow). The name
is picked up by the call to PrJobDialog (or PrValidate if you ain't using
a dialog (tut tut)).
While on print jobs the following may be of interest. IM Vol II implies
that in the TPrint structure, prJob.iCopies can be used to examine the
number of copies specified in the print dialog (Think Reference says this
explicitly). My experience (with the Laserwrite 8 driver) is that
prJob.iCopies stays obstinately at 1, but prXInfo.iRowBytes *does* reflect
the number of copies (and can be used to *set* the number of copies for
that matter).
Seems a bit odd to have a field documented for the purpose and then use a
different one, but presumably I shouldn't be messing with the print copies
anyway!
- -----------------------SDR Clinical Technology------------------------
213 Eastern Valley Way, Middle Cove, NSW 2068, Australia
Voice: +61-2-9958-2688 Fax: +61-2-9958-2655 email: sdr@sdr.com.au
World Wide Web: http://www.sdr.com.au/sdr/index.html
- ----------------------------------------------------------------------
+++++++++++++++++++++++++++
>From dowdy@apple.com (Tom Dowdy)
Date: Thu, 18 Jan 1996 16:41:17 GMT
Organization: Apple Computer, Inc.
In article <sdr-1501961047080001@gateway.sdr.com.au>, sdr@sdr.com.au
(Roger Lainson) wrote:
> Thanks to everybody who helped with my query about how to name a printer
> job. The concensus of the comments (plus a few experiments) is that the
> job name takes the name of the frontmost window, which must be visible but
> which can be offscreen. Floaters are ignored (as in FrontWindow). The name
> is picked up by the call to PrJobDialog (or PrValidate if you ain't using
> a dialog (tut tut)).
>
> While on print jobs the following may be of interest. IM Vol II implies
> that in the TPrint structure, prJob.iCopies can be used to examine the
> number of copies specified in the print dialog (Think Reference says this
> explicitly). My experience (with the Laserwrite 8 driver) is that
> prJob.iCopies stays obstinately at 1, but prXInfo.iRowBytes *does* reflect
> the number of copies (and can be used to *set* the number of copies for
> that matter).
>
> Seems a bit odd to have a field documented for the purpose and then use a
> different one, but presumably I shouldn't be messing with the print copies
> anyway!
When you use the QuickDraw GX printing APIs you can *directly* specify
to the print record both your document name, and the number of copies.
In fact, you can set EVERY SINGLE thing that a user might set in the
print dialog yourself through a public API, with no mucking about.
In addition, GX directly supports dialogless (including no status
dialogs) printing, so you don't have to muck about to get that either.
I mention this because it's pretty much a one for one translation of
your existing print loop to use GX printing when it's available.
This way, you get neat cool new features when GX is there, but
still run as you do today when it is not.
SimpleText does this, and it really is very trivial. Details on how
to do it appear in a _develop_ article by Dave Hersey a while back.
Anyway, it's something you should consider when working on an application.
--
Tom Dowdy Internet: dowdy@apple.COM
Apple Computer MS:302-3KS UUCP: {sun,voder,amdahl,decwrl}!apple!dowdy
1 Infinite Loop AppleLink: DOWDY1
Cupertino, CA 95014
"The 'Ooh-Ah' Bird is so called because it lays square eggs."
---------------------------
>From Charles Thomas <cfthoma1@facstaff.wisc.edu>
Subject: Problems with UPP's
Date: 4 Jan 1996 17:12:13 GMT
Organization: IMR, University of Wisconsin-Madison
Hi.
Still struggling with properly implementing the use of UPP's. Mostly,
the books I've got use ControlProc's as examples. My specific code is
below and it doesn't work, so I'm obviously doing something wrong. I'm
trying to replace a GrowZoneProcPtr with a UniversalProcPtr.
What I'd like to know is what the correct code should be and how to find
out the correct parameters to pass NewRoutineDescriptor, specifically the
second and third parameters.
Thanks for any help.
//*******CODE FOLLOWS*****
//emergency_memory is an external global variable
void initialize_emergency_memory (void)
{
UniversalProcPtr my_growzoneUPP = NIL;
emergency_memory = NewHandle(EMERGENCY_MEMORY_SIZE);
if (emergency_memory == NIL)
{
put_message("\pThere has been a memory allocation error.");
ExitToShell();
}
my_growzoneUPP = NewRoutineDescriptor((ProcPtr)MyGrowZone,
kPascalStackBased, kPowerPCISA);
SetGrowZone(my_growzoneUPP);
DisposeRoutineDescriptor(my_growzoneUPP);
//**** The above three lines replace the following line from the 68k code:
// SetGrowZone((GrowZoneProcPtr)&MyGrowZone);
return;
}// end of initialize_emergency_memory()
+++++++++++++++++++++++++++
>From vance@webgenesis.com (Vance Huntley)
Date: Thu, 04 Jan 1996 19:13:23 -0500
Organization: WebGenesis, Inc.
In article <4ch1pd$2092@news.doit.wisc.edu>, Charles Thomas
<cfthoma1@facstaff.wisc.edu> wrote:
> Hi.
>
> Still struggling with properly implementing the use of UPP's. Mostly,
> the books I've got use ControlProc's as examples. My specific code is
> below and it doesn't work, so I'm obviously doing something wrong. I'm
> trying to replace a GrowZoneProcPtr with a UniversalProcPtr.
>
> What I'd like to know is what the correct code should be and how to find
> out the correct parameters to pass NewRoutineDescriptor, specifically the
> second and third parameters.
The trick is to use the UPP stuff defined for you in the UniversalHeaders
wherever possible. I believe that they have macros for creating UPP's
appropriate for every callback in the Toolbox.
Try this:
[clip]
GrowZoneUPP myGrowZoneUPP = NewGrowZoneProc(MyGrowZone);
> SetGrowZone(myGrowZoneUPP);
and DONT DISPOSE OF THE ROUTINE DESCRIPTOR, since the mixed mode manager
will need it whenever the routine is actually called. The memory will be
freed automatically when your app quits.
Good Luck-
Vance
+++++++++++++++++++++++++++
>From zobkiw@triplesoft.com (Joe Zobkiw)
Date: Thu, 04 Jan 1996 19:34:13 -0500
Organization: TripleSoft Inc.
In article <4ch1pd$2092@news.doit.wisc.edu>, Charles Thomas
<cfthoma1@facstaff.wisc.edu> wrote:
>Still struggling with properly implementing the use of UPP's.
::: stuff deleted :::
> my_growzoneUPP = NewRoutineDescriptor((ProcPtr)MyGrowZone,
> kPascalStackBased, kPowerPCISA);
Look in memory.h and use the NewGrowZoneProc macro that is there. You can
then use the resulting GrowZoneUPP as your UPP.
Good luck!
Joe Zobkiw <mailto:zobkiw@triplesoft.com>
TripleSoft Inc. <http://www.triplesoft.com/>
Specializing in Custom Macintosh Software Development & Solutions
- ---------------------------------------------------------------
Macintosh programmers! Check out "A Fragment of Your Imagination"
from Addison-Wesley <http://www.triplesoft.com/fragment/>
+++++++++++++++++++++++++++
>From DaveZ@mailbag.com (David B. Zwiefelhofer)
Date: Fri, 05 Jan 1996 11:56:51 -0500
Organization: Utility Reduction Specialists, Inc.
In article <vance-0401961913230001@mainframe.webgenesis.com>,
vance@webgenesis.com (Vance Huntley) wrote:
[snip]
>
> and DONT DISPOSE OF THE ROUTINE DESCRIPTOR, since the mixed mode manager
> will need it whenever the routine is actually called. The memory will be
> freed automatically when your app quits.
>
Really? Now I'm confused. When can I and when can I not use
DisposeRoutineDescriptor?
Thanks,
Dave
--
David B. Zwiefelhofer
Utility Reduction Specialists, Inc.
1605 Monroe Street, Suite 110
Madison, WI 53211-2052
(608) 258-8965
(608) 258-9686 FAX
+++++++++++++++++++++++++++
>From "Andrew C. Plotkin" <erkyrath+@CMU.EDU>
Date: Fri, 5 Jan 1996 20:14:02 -0500
Organization: Carnegie Mellon, Pittsburgh, PA
DaveZ@mailbag.com (David B. Zwiefelhofer) writes:
> In article <vance-0401961913230001@mainframe.webgenesis.com>,
> vance@webgenesis.com (Vance Huntley) wrote:
>
> [snip]
> >
> > and DONT DISPOSE OF THE ROUTINE DESCRIPTOR, since the mixed mode manager
> > will need it whenever the routine is actually called. The memory will be
> > freed automatically when your app quits.
> >
>
> Really? Now I'm confused. When can I and when can I not use
> DisposeRoutineDescriptor?
It's like any other allocated object; you can dispose of it once
you're sure that it will never be used again.
For example, if I'm passing a file-filter callback in to
StandardGetFile, I usually allocate the routine descriptor before
calling StandardGetFile and dispose of it afterwards. That's because I
know that the toolbox will only call it during that StandardGetFile
call.
But if you create a descriptor and put it somewhere where it will be
used for the rest of your program's lifetime, you shouldn't dispose of
it until the end of that lifetime.
--Z
"And Aholibamah bare Jeush, and Jaalam, and Korah: these were the borogoves..."
+++++++++++++++++++++++++++
>From DaveZ@mailbag.com (David B. Zwiefelhofer)
Date: Fri, 12 Jan 1996 16:08:14 -0500
Organization: Utility Reduction Specialists, Inc.
In article <kkvQnOC00WB3Mfb8AC@andrew.cmu.edu>, "Andrew C. Plotkin"
<erkyrath+@CMU.EDU> wrote:
> DaveZ@mailbag.com (David B. Zwiefelhofer) writes:
> > In article <vance-0401961913230001@mainframe.webgenesis.com>,
> > vance@webgenesis.com (Vance Huntley) wrote:
> >
> > [snip]
> > >
> > > and DONT DISPOSE OF THE ROUTINE DESCRIPTOR, since the mixed mode manager
> > > will need it whenever the routine is actually called. The memory will be
> > > freed automatically when your app quits.
> > >
> >
> > Really? Now I'm confused. When can I and when can I not use
> > DisposeRoutineDescriptor?
>
> It's like any other allocated object; you can dispose of it once
> you're sure that it will never be used again.
>
> For example, if I'm passing a file-filter callback in to
> StandardGetFile, I usually allocate the routine descriptor before
> calling StandardGetFile and dispose of it afterwards. That's because I
> know that the toolbox will only call it during that StandardGetFile
> call.
>
> But if you create a descriptor and put it somewhere where it will be
> used for the rest of your program's lifetime, you shouldn't dispose of
> it until the end of that lifetime.
>
Well, that makes sense. But now I'm truly confused. I have used the UPPs
for apple event handlers. The thing that confuses me is that I was
disposing of them immediately after AEInstallEventHandler-ing them
*without* any problems. I haven't compiled this for PPC yet.
So can you elaborate further on this? Why is this working for me?
Something to do with 68K as opposed to PPC?
Thanks,
Dave
--
David B. Zwiefelhofer
Utility Reduction Specialists, Inc.
1605 Monroe Street, Suite 110
Madison, WI 53211-2052
(608) 258-8965
(608) 258-9686 FAX
+++++++++++++++++++++++++++
>From tulip@tiac.net (Ed Anson)
Date: Fri, 12 Jan 1996 21:38:42 -0500
Organization: Tulip Software
In article <DaveZ-1201961608140001@msn_3_1.binc.net>, DaveZ@mailbag.com
(David B. Zwiefelhofer) wrote:
> Well, that makes sense. But now I'm truly confused. I have used the UPPs
> for apple event handlers. The thing that confuses me is that I was
> disposing of them immediately after AEInstallEventHandler-ing them
> *without* any problems. I haven't compiled this for PPC yet.
>
> So can you elaborate further on this? Why is this working for me?
> Something to do with 68K as opposed to PPC?
YES.
When compiling for 68K, the macros for creating UPPs just return procedure
pointers. The macros for disposing UPPs do absolutely nothing. So the
installed event handler still works even after you "dispose" of the UPP.
But when you compile for PPC those macros actually allocate and dispose
blocks of memory containing the magic PPC stuff. In this case, if you
dispose the UPP, the event handler won't work and you will probably crash,
because the system will branch into a block of freed memory.
- --------------------
Ed Anson
Tulip Software
Andover, MA 01810 Check out my WWW page:
U.S.A. <http://www.tiac.net/users/tulip/home.html>
+++++++++++++++++++++++++++
>From dnebing@epix.net (Dave Nebinger)
Date: Mon, 15 Jan 1996 13:54:47 -0500
Organization: KHP Services, Inc
In article <DaveZ-1201961608140001@msn_3_1.binc.net>, DaveZ@mailbag.com
(David B. Zwiefelhofer) wrote:
> Well, that makes sense. But now I'm truly confused. I have used the UPPs
> for apple event handlers. The thing that confuses me is that I was
> disposing of them immediately after AEInstallEventHandler-ing them
> *without* any problems. I haven't compiled this for PPC yet.
The reason you haven't seen any problems yet is because you haven't
compiled for PPC. 68k code doesn't use UPPs (until the 68k CFM is
available), so your quick disposal doesn't really do anything (if you look
at the code you are generating, NewRoutineDescriptor() and
DisposeRoutineDescriptor() expand to nothing for 68k compilers).
When you move to PPC/CFM compilation, that's when your method
will fail miserably. Your best bet is just to create the routines
and forget about them (unless they are system handlers; those you
will have to dispose of later). After your app dies all of the memory
that you have allocated is returned to the system so you don't have
to worry about upp's being stranded.
Dave.
==========================================================
Dave Nebinger dnebing@epix.net
The Alt.Sources.Mac Archivist
---------------------------
>From kryan@aoc.nrao.edu (Kevin Ryan)
Subject: Q: Do QuickDraw routines execute faster Offscreen?
Date: 10 Jan 1996 16:07:10 GMT
Organization: National Radio Astronomy Observatory
My Daughter and I are doing a project in cellular automata and have a screen
of dozens of little QuickDraw Regions ('cells') roaming around looking for
'food' (using GetCPixel). As is no surprise, most of the program time is
spent on the screen. We envision long running (overnight) experiments where
we want to perform as many cycles as fast as possible, but won't be watching
the screen. The operation of the program however, depends on the QuickDraw
routines (i.e. if GetCPixel returns a 'food' - he don't go hungry!).
My question is: can we implement a 'fast-forward' function by moving the
screen routines to an offscreen GWorld (we would give up being able to
see what was happening for the sake of speed). Will the same QuickDraw
routines execute faster offscreen where there is no actual screen drawing
taking place?
I've read the Inside Mac books and Technical Notes but they all simply say
that offscreen drawing makes for smoother screen updates - "you can create
the image offscreen, then update the screen when it is all done". This
does not tell me if the QuickDraw routines will execute faster or not.
My daughter's Mac has built-in video and mine uses an old 8-bit NuBus card.
Thank you,
Kevin Ryan
--
- -----------------------------------------------------------------------------
Kevin Ryan National Radio Astronomy Observatory
Scientific Programmer Array Operations Center
kryan@aoc.nrao.edu P.O. Box O Socorro, NM 87801
- -----------------------------------------------------------------------------
+++++++++++++++++++++++++++
>From pottier@felouque.ens.fr (Francois Pottier)
Date: 11 Jan 1996 13:56:46 GMT
Organization: Ecole Normale Superieure, Paris
In article <4d0o7e$9vj@chaos.aoc.nrao.edu>,
Kevin Ryan <kryan@aoc.nrao.edu> wrote:
>My question is: can we implement a 'fast-forward' function by moving the
>screen routines to an offscreen GWorld (we would give up being able to
>see what was happening for the sake of speed). Will the same QuickDraw
>routines execute faster offscreen where there is no actual screen drawing
>taking place?
Yes, QuickDraw is faster offscreen, because it doesn't have to perform
various tests to see which monitor the pixel is falling into, which
window & palette are active, etc. I don't know whether the speed
difference is substantial, though.
However, the biggest advantage of using offscreen worlds is that you
can then stop using SetCPixel and GetCPixel, which are very, very slow.
Instead you can very easily roll your own routines. The basic idea is
this: use GetGWorldPixMap to obtain a handle to the world's pixmap,
then GetPixBaseAddr to get the pixmap's base address. Once this is
done, do a simple computation to convert a (x, y) pair into an
offset into the pixmap. Basically
rowBytes * y + x
in 8 bit mode (you would use 2*x in 16 bit mode, etc.). Once you
know the address of the point, you can write or read its color
easily. This is several orders of magnitude faster than Get/SetCPixel.
This kind of trick should be used only on offscreen worlds, because
it is more complex with the screen itself (several monitors, dealing
with video RAM, etc.)
I hope this helps,
--
Francois
pottier@dmi.ens.fr
http://www.eleves.ens.fr:8080/home/pottier/
+++++++++++++++++++++++++++
>From s868672@umslvma.umsl.edu (Tracy Findley)
Date: 11 Jan 1996 17:55:45 GMT
Organization: University of Missouri - St. Louis
In article <4d0o7e$9vj@chaos.aoc.nrao.edu>, kryan@aoc.nrao.edu wrote:
> My Daughter and I are doing a project in cellular automata and have a screen
> of dozens of little QuickDraw Regions ('cells') roaming around looking for
> 'food' (using GetCPixel). As is no surprise, most of the program time is
> spent on the screen. We envision long running (overnight) experiments where
> we want to perform as many cycles as fast as possible, but won't be watching
> the screen. The operation of the program however, depends on the QuickDraw
> routines (i.e. if GetCPixel returns a 'food' - he don't go hungry!).
>
> My question is: can we implement a 'fast-forward' function by moving the
> screen routines to an offscreen GWorld (we would give up being able to
> see what was happening for the sake of speed). Will the same QuickDraw
> routines execute faster offscreen where there is no actual screen drawing
> taking place?
>
> I've read the Inside Mac books and Technical Notes but they all simply say
> that offscreen drawing makes for smoother screen updates - "you can create
> the image offscreen, then update the screen when it is all done". This
> does not tell me if the QuickDraw routines will execute faster or not.
>
> My daughter's Mac has built-in video and mine uses an old 8-bit NuBus card.
>
> Thank you,
> Kevin Ryan
>
Yes, provisionally. When QuickDraw has to write to the screen, no caching
can be done so memory access occurs more slowly for drawing to the screen;
_if_ caching is available for that particular machine.
Second: for fantastic speed-ups; forget about GetCPixel and use offscreen
GWorlds and access the pixels yourself; check out "Develop Issue 10" found
at
http://www.info.apple.com
somewhere in "Developer Services." The article "Drawing in GWorlds for
Speed and Versatility" describes in detail how to do exactly what you
want. They took a routine that used GetCPixel and SetCPixel to perform an
operation on an image and replaced it so that instead of taking 10 seconds
it took about 1/60th of a second!
You _will_ have to blit the gworld back to the screen as often as you want
to see it, of course.
Hope this helps,
David Findley
--
Tracy Findley
s868672@umslvma.umsl.edu
+++++++++++++++++++++++++++
>From Mark Barton <mbarton@icrr.u-tokyo.ac.jp>
Date: Fri, 19 Jan 1996 06:26:57 GMT
Organization: Institute for Cosmic Ray Research, Tokyo Uni.
In article <4d0o7e$9vj@chaos.aoc.nrao.edu> Kevin Ryan, kryan@aoc.nrao.edu
writes:
>Subject: Q: Do QuickDraw routines execute faster Offscreen?
>From: Kevin Ryan, kryan@aoc.nrao.edu
>Date: 10 Jan 1996 16:07:10 GMT
>>My Daughter and I are doing a project in cellular automata and have a screen
>of dozens of little QuickDraw Regions ('cells') roaming around looking for
>'food' (using GetCPixel). As is no surprise, most of the program time is
>spent on the screen. We envision long running (overnight) experiments where
>we want to perform as many cycles as fast as possible, but won't be watching
>the screen. The operation of the program however, depends on the QuickDraw
>routines (i.e. if GetCPixel returns a 'food' - he don't go hungry!).
>
>My question is: can we implement a 'fast-forward' function by moving the
>screen routines to an offscreen GWorld (we would give up being able to
>see what was happening for the sake of speed). Will the same QuickDraw
>routines execute faster offscreen where there is no actual screen drawing
>taking place?
>
>I've read the Inside Mac books and Technical Notes but they all simply say
>that offscreen drawing makes for smoother screen updates - "you can create
>the image offscreen, then update the screen when it is all done". This
>does not tell me if the QuickDraw routines will execute faster or not.
>
>My daughter's Mac has built-in video and mine uses an old 8-bit NuBus card.
Yes you are definitely thinking along the right lines. There is a
particularly large amount of overhead in each call to the graphics
routines so the more procedure calls you can eliminate the better. I
wrote such a game once and after a lot of trial and error achieved a
speedup of a factor of thirty or more.
The fastest way to do this of course is to interrogate QuickDraw to
find out where the screen is and write to it directly. However this
requires you to write and debug a lot of arithmetic and the details of
the arithmetic depend on the screen size, screen depth, window
position etc. Unless you spend a lot of effort allowing for different
cases the program will be completely non-portable.
A better method which is nearly as fast is to maintain the cellular
automaton world in an array offscreen which is of the right size and
shape to work as a bitmap or pixmap. There are a few rules, such as
that there have to be an even number of bytes in each row, but
generally you get to choose. Create a grafPort or cGrafPort of the
right size and shape to match your array and install a pointer to the
array in it. Then simply use CopyBits to copy the array to the
physical screen. By using the scale parameters to CopyBits you can
make the on-screen pixels any size you like.
I was working with a particular system which was most interesting with
around 16-20 states per cell, so I chose an array of bytes and told
QuickDraw that it was a 256 colour pixmap. If you are programming
something like Life with two states then you can make the array a
simple (black and white) bitmap. Most programming languages are not
set up to handle arrays of bits but it is trivial to write functions
or macros which will do the job.
I can send you some Pascal or C code if you are interested. It
doesn't actually work, but it's very very close. The Pascal version
did work but broke mysteriously when I upgraded to System 7 for
reasons I never managed to work out, and the C is a translation which
is fully debugged except for the same error as in the Pascal(!).
Cheers,
Mark B.
---------------------------
>From Carl R. Osterwald <carl_osterwald@nrel.gov>
Subject: SetCCursor inside a VBL task?
Date: 18 Jan 1996 22:37:36 GMT
Organization: National Renewable Energy Laboratory
I have used SetCCursor inside a VBL task to produce an animated cursor
without problems for several years, but now find that it crashes on a
7200 running 7.5.2 (using SetCursor with a B&W cursor does not crash).
Is there something inherently wrong with doing this, or is there a way
around it?
+++++++++++++++++++++++++++
>From mclow@mailhost2.csusm.edu (Marshall Clow)
Date: Sat, 20 Jan 1996 22:25:32 -0800
Organization: Aladdin Systems
In article <4dmi3g$n1l@nrel.nrel.gov>, Carl R. Osterwald
<carl_osterwald@nrel.gov> wrote:
>I have used SetCCursor inside a VBL task to produce an animated cursor
>without problems for several years, but now find that it crashes on a
>7200 running 7.5.2 (using SetCursor with a B&W cursor does not crash).
>Is there something inherently wrong with doing this, or is there a way
>around it?
>
You can't do anything inside a VBL completion routine that will move memory.
I don't see anything in Inside Mac that says either way if SetCCursor
moves memory. However, IM-V pp 75 says: "At the time the cursor is set, it
is expanded to the current screen depth so that it can be drawn rapidly."
That sounds to me like allocating/resizing memory.
--
Marshall Clow
Aladdin Systems
"They that can give up essential liberty to obtain a little temporary
safety deserve neither liberty nor safety." -- Benjamin Franklin
_Historical Review of Pennsylvania_, 1759
+++++++++++++++++++++++++++
>From rickgenter@aol.com (RickGenter)
Date: 19 Jan 1996 10:02:02 -0500
Organization: America Online, Inc. (1-800-827-6364)
>>>
Is there something inherently wrong with doing this, or is there a way
around it?
<<<
I believe SetCCursor is documented as potentially moving memory, which you
can not do safely within a VBL handler.
Rick Genter
Papyrus Design Group, Inc.
---------------------------
>From dunham@pensee.com (David Dunham)
Subject: Using STL with pointers to objects
Date: Tue, 02 Jan 1996 22:30:58 -0800
Organization: Pensee Corporation
I'm trying to convert the ODFDraw sample to an editor which keeps track of
an array (rather than an ordered list) of embedded parts. Since ODF
doesn't have an array class, I decided to try to use STL as the basis for
my array. The abbreviated header is
class FW_CLASS_ATTR CThingList {
unsigned long Count() const { return fImplementation.size(); }
FW_Boolean IsEmpty() const { return fImplementation.empty(); }
CThing* First() { return fImplementation.empty()
? kODNULL : fImplementation.front(); }
CThing* Last() { return fImplementation.back(); }
CThing* Nth(const long aPos) { return fImplementation[aPos]; }
void AddLast(CThing* anElement) {
fImplementation.push_back(anElement); }
private:
vector<CThing*> fImplementation;
};
And this all seems to work, except that when a CThingList is destroyed,
~CThing is never called. I've yet to see an example of STL vectors which
are an array of pointers, rather than an array of objects.
Should I be using vector<CThing> instead? If so, how would I dynamically
allocate CThings to add to the list?
David Dunham Pensee Corporation dunham@pensee.com
Voice/Fax: 206 783 7404 http://www.pensee.com/dunham/
"I say we should listen to the customers and give them what they want."
"What they want is better products for free." --Scott Adams
+++++++++++++++++++++++++++
>From kenp@nmrfam.wisc.edu (Ken Prehoda)
Date: Wed, 03 Jan 1996 09:18:14 -0600
Organization: Univ of Wisconsin-Madison, Dept of Biochemistry
In article <dunham-0201962230580001@feather.pensee.com>, dunham@pensee.com
(David Dunham) wrote:
: I'm trying to convert the ODFDraw sample to an editor which keeps track of
: an array (rather than an ordered list) of embedded parts. Since ODF
: doesn't have an array class, I decided to try to use STL as the basis for
: my array. The abbreviated header is
:
: class FW_CLASS_ATTR CThingList {
: unsigned long Count() const { return fImplementation.size(); }
: FW_Boolean IsEmpty() const { return
fImplementation.empty(); }
:
: CThing* First() { return fImplementation.empty()
: ? kODNULL : fImplementation.front(); }
: CThing* Last() { return fImplementation.back(); }
: CThing* Nth(const long aPos) { return fImplementation[aPos]; }
:
: void AddLast(CThing* anElement) {
: fImplementation.push_back(anElement); }
:
: private:
: vector<CThing*> fImplementation;
: };
:
: And this all seems to work, except that when a CThingList is destroyed,
: ~CThing is never called. I've yet to see an example of STL vectors which
: are an array of pointers, rather than an array of objects.
If you store pointers to objects, you have to handle their destruction yourself.
: Should I be using vector<CThing> instead? If so, how would I dynamically
: allocate CThings to add to the list?
It is better to have stl store the objects themselves. Sometimes you are
forced to store pointers, however. An example would be storing
heterogenous objects that descend from a common base class.
To dynamically add CThing's to the vector
CThing aThing;
fImplementation.push_back(aThing);
or
CThing* aThing = new CThing;
fImplementation.push_back(*aThing);
delete aThing;
_____________________________________________________________________________
Ken Prehoda kenp@nmrfam.wisc.edu
Department of Biochemistry http://www.nmrfam.wisc.edu
University of Wisconsin-Madison Tel: 608-263-9498
420 Henry Mall Fax: 608-262-3453
+++++++++++++++++++++++++++
>From Garth Cummings <gcummings@amoco.com>
Date: 3 Jan 1996 15:16:02 GMT
Organization: Vysis, Inc.
Generally STL classes are used to contain objects by value rather than by
reference. Thus a vector<CThing> is more idiomatic than vector<CThing*>.
STL containers contain copies of the objects that are inserted to the
container.
However, a container of pointers is perfectly valid with a couple of
caveats. First, you become responsible for managing the creation and
deletion of objects whose addresses are in the container. Second, if you
are using an ordered container such as set, you will probably want to
provide an operator> and operator== for your pointers that dereference
the pointers to compare some attribute of the actual objects. Otherwise
the set would be ordered on the addresses themselves.
I've found the Web site
http://www.xraylith.wisc.edu/~khan/software/stl/STL.newbie.html very
useful for getting help, sample code, etc. on STL.
Cheers,
Garth
Garth Cummings
Project Leader
Vysis, Inc.
+++++++++++++++++++++++++++
>From fuz@deltanet.com (Scott Ellsworth)
Date: 3 Jan 1996 19:32:07 GMT
Organization: Deltanet Communications, Inc.
In article <dunham-0201962230580001@feather.pensee.com>,
David Dunham <dunham@pensee.com> wrote:
> vector<CThing*> fImplementation;
>And this all seems to work, except that when a CThingList is destroyed,
>~CThing is never called. I've yet to see an example of STL vectors which
>are an array of pointers, rather than an array of objects.
>
>Should I be using vector<CThing> instead? If so, how would I dynamically
>allocate CThings to add to the list?
>
Have you read Mumit Khan's STL page and the many pages devoted to it at
rpi? When I needed to do this, I found them a great help. The solution
I chose was a wrapper class, called a BuildingHolder. Essentially, it
was a smart pointer which handled the deletion of the object pointed to,
and which was otherwise fairly trivial.
e.g. (from memory)
class BuildingHolder {
public:
BuildingHolder() { held=0; }
BuldingHolder(const Building & in) { held=in; }
BuldingHolder(const BuildingHolder & in) { held=in.MakeCopy(); }
~BuildingHolder() { if (held) delete held; }
Building * GetIt(void) { return held; }
Building * MakeCopy(void) { ... code to copy with ref counts ... }
private:
Building * held;
};
There was also some reference counting to make copies efficient and safe,
but I suspect you get the idea. In addition, you will need the usual ==.
=, <, etc., that are aware of the refence counting.
Then, my lists, vectors, etc., became vector<BuildingHolder>, and so on.
Also aided the introduction of leak detection diagnostics.
Scott
--
Scott Ellsworth fuz@deltanet.com
"When a great many people are unable to find work, unemployment
results" - Calvin Coolidge, (Stanley Walker, City Editor, p. 131 (1934))
"The barbarian is thwarted at the moat." - Scott Adams
+++++++++++++++++++++++++++
>From dunham@pensee.com (David Dunham)
Date: Wed, 03 Jan 1996 18:22:29 -0800
Organization: Pensee Corporation
In article <4celjn$6ac@news2.deltanet.com>, fuz@deltanet.com (Scott
Ellsworth) wrote:
> Have you read Mumit Khan's STL page and the many pages devoted to it at
> rpi? When I needed to do this, I found them a great help. The solution
> I chose was a wrapper class, called a BuildingHolder. Essentially, it
> was a smart pointer which handled the deletion of the object pointed to,
> and which was otherwise fairly trivial.
Yeah, I finally figured it out (in part thanks to that page). No help at
all from "STL Tutorial and Reference Guide" by Musser and Saini :-( I
needed to do the two things that STL can't -- hold subclassed items, and
have the same item in multiple containers.
> There was also some reference counting to make copies efficient and safe,
Does this mean all of your Building had to be in BuildingHolder?
> Also aided the introduction of leak detection diagnostics.
I assume it was the reference counting that helped with leaks?
David Dunham Pensee Corporation dunham@pensee.com
Voice/Fax: 206 783 7404 http://www.pensee.com/dunham/
"I say we should listen to the customers and give them what they want."
"What they want is better products for free." --Scott Adams
+++++++++++++++++++++++++++
>From fuz@deltanet.com (Scott Ellsworth)
Date: 4 Jan 1996 18:42:44 GMT
Organization: Deltanet Communications, Inc.
In article <dunham-0301961822290001@feather.pensee.com>,
David Dunham <dunham@pensee.com> wrote:
>In article <4celjn$6ac@news2.deltanet.com>, fuz@deltanet.com (Scott
>Ellsworth) wrote:
>
>> Have you read Mumit Khan's STL page and the many pages devoted to it at
>> rpi? When I needed to do this, I found them a great help. The solution
>> I chose was a wrapper class, called a BuildingHolder. Essentially, it
>> was a smart pointer which handled the deletion of the object pointed to,
>> and which was otherwise fairly trivial.
>
>Yeah, I finally figured it out (in part thanks to that page). No help at
>all from "STL Tutorial and Reference Guide" by Musser and Saini :-( I
>needed to do the two things that STL can't -- hold subclassed items, and
>have the same item in multiple containers.
My personal favorite book on it presently is the Nelson book. I am
eyeing the STL<primer> book as well, since it seems to have a better
discussion of some of the recent things from ObjectSpace. Musser's book
did not do much for me, but that might be because I have already read
all of his pages at rpi, and so have already seen many of the things they
were talking about.
I have found that STL can hold subclassed items and can hold multiple
containers, as long as you are rather careful, and that the things that
STL is holding are unique. (i.e., I might have three BuildingHolders
which hold the same thing, or which hold Buildings and Building
subclasses, and STL does not mind.) I have had success making it just
hold pointers, but there are enough gotchas that some kind of wrapper has
saved me a fair amount of grief. I am thinking of making a templated
holder class, given that my holders have looked pretty similar the last
few times I have needed to use them.
>> There was also some reference counting to make copies efficient and safe,
>
>Does this mean all of your Building had to be in BuildingHolder?
No, only those buldings that I wanted to put in STL structures and that I
wanted to reference count. Given the leak detection I also wanted, I
ended up putting them all in BuildingHolder, and bulked up BuldingHolder
from a smart pointer to a combination smart pointer and factory class.
>
>> Also aided the introduction of leak detection diagnostics.
>
>I assume it was the reference counting that helped with leaks?
Yep. Also, I discovered DebugNew about the same time. After stealing a
few ideas from that, I put in a call to TickCount on creation and a
vector in each object storing the time when the object was created, and
matched it for deletions. Ended up very slow, but helped when I was
trying to find why I was drizzling memory all over the place.
A better solution was to have a counter that incremented on each
creation, so if I ended up leaking, I could peer into memory and see
which object was not being freed. Not helpful if it was one in the
middle, but very handy when I had an off-by-one error that was not
freeing the first object allocated.
Scott
--
Scott Ellsworth fuz@deltanet.com
"When a great many people are unable to find work, unemployment
results" - Calvin Coolidge, (Stanley Walker, City Editor, p. 131 (1934))
"The barbarian is thwarted at the moat." - Scott Adams
+++++++++++++++++++++++++++
>From "Joseph N. Hall" <joseph@5sigma.com>
Date: 15 Jan 1996 04:01:09 GMT
Organization: 5 Sigma Productions
dunham@pensee.com (David Dunham) wrote:
>Yeah, I finally figured it out (in part thanks to that page). No help at
>all from "STL Tutorial and Reference Guide" by Musser and Saini :-( I
>needed to do the two things that STL can't -- hold subclassed items, and
>have the same item in multiple containers.
Err, to handle the subclassing problem, create template classes derived
from the container class. The template class(es) should perform the
type coercions to/from the class of objects that the base container
class manipulates. In other words:
class ObjectBase = base object class
class ObjectDerived1, ObjectDerived2 ... = classes derived from above
class ContainerBase = base container class = container of ObjectBase
class ContainerDerived1 = template class derived from ContainerBase
that does type coercions of ObjectDerived1 to/from ObjectBase but
otherwise lets ContainerBase do the work = container of ObjectDerived1
========================================================================
Joseph N. "Moof-in'" Hall Proprietor, V V sssss
joseph@5sigma.com 5 Sigma Productions V V s s
P.O. Box 6250 software, multimedia, original music V V s s
Chandler AZ 85246 http://www.5sigma.com/joseph/Joseph.html V sss
---------------------------
>From johnd@geko.net.au (John Dalgliesh)
Subject: VBL synching (again)
Date: 17 Jan 1996 11:18:50 GMT
Organization: Slipped Disk Software
This is the first of two ideas which I had for possible implementaion in games.
I don't know if they have been mentioned b4 or if they are already used, which
is why I'm asking about their feasiblity now.
OK, say we have a VBL routine which sets a variable (it'd just have a ptr
to it) to the current time (obviously in a resultion better than ticks -
say
microseconds). Now at init time in the game it times how long it takes for
one VBL (or 8 and divides it by 8 - whatever) to go past. When it comes
time to blit to the screen from your offscreen gworld, you get the last
VBL time, get the current time, and using the time for one beam cycle
figure out where the beam is - and start blitting just behind it (or
exactly half way away from it - whatever method stops tearing). Note that
this could easily be adapted to two copybits calls if you don't want to
write a special blitter.
However, the time which the beam takes to go from the bottom of the screen
back to the top must be taken into account - more importantly, does the
VBL occur when it's just reached the bottom or when it's just returned to
the top? Anyway, I would suppose that the majority of it's time is spent
actually on the screen, so this is a relatively minor issue...
So how about it folks? Is there anything majorly flawed with this
technique? Has it already been implemented and I've been missing out or
something :-) ?
TIA
{*^/
+++++++++++++++++++++++++++
>From rickgenter@aol.com (RickGenter)
Date: 18 Jan 1996 09:12:30 -0500
Organization: America Online, Inc. (1-800-827-6364)
>>>
OK, say we have a VBL routine which sets a variable (it'd just have a ptr
to it) to the current time (obviously in a resultion better than ticks -
say
microseconds).
[more details deleted]
<<<
The Vertical Retrace Manager is tricky to use for avoiding tearing for a
number of reasons:
1) Using VInstall() won't work unless you are on an original Macintosh.
VInstall()ed tasks are run 60.15 times per second, to match the vertical
blank time on the original Macintosh.
2) On a multiple monitor system, each monitor has its own vertical refresh
rate. While you can use SlotVInstall() to synchronize to each monitor, you
will have to update each monitor asynchronously with respect to the other
monitors. (Or limit your game to a single monitor.) Tearing would look
better :-).
3) Unless your game already has an incredibly high frame rate (> 60 FPS),
tearing shouldn't be a priority.
Just MHO.
Rick Genter
Papyrus Design Group, Inc.
+++++++++++++++++++++++++++
>From jmunkki@beta.hut.fi (Juri Munkki)
Date: 19 Jan 1996 16:56:46 GMT
Organization: Helsinki University of Technology
In article <johnd-1701962224000001@dialup202.geko.net.au> johnd@geko.net.au (John Dalgliesh) writes:
>However, the time which the beam takes to go from the bottom of the screen
>back to the top must be taken into account - more importantly, does the
>VBL occur when it's just reached the bottom or when it's just returned to
>the top? Anyway, I would suppose that the majority of it's time is spent
>actually on the screen, so this is a relatively minor issue...
The VBL interrupt comes the moment when the video memory is no longer
being accessed, but then it goes into the interrupt handler and there
are other tasks (most notably the mouse) usually before your task.
I seem to remember a note saying that it is possible to insert a task
before all other tasks. This would be necessary for even remotely
accurate timing (the mouse can consume wildly varying amounts of time).
Then you are still at the mercy of other interrupts that may cause
the VBL interrupt to be delayed.
My opinion s that it is not worth the effort unless you are programming
for 3D shutter glasses (something I did years ago).
--
Juri Munkki jmunkki@iki.fi Life is easy when polygons are cheap.
http://www.iki.fi/jmunkki Windsurfing: Faster than the wind.
---------------------------
End of C.S.M.P. Digest
**********************